<?php
//
// FPDI - Version 1.3.1
//
// Copyright 2004-2009 Setasign - Jan Slabon
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
class FilterLZW {
	var $sTable = array ();
	var $data = null;
	var $dataLength = 0;
	var $tIdx;
	var $bitsToGet = 9;
	var $bytePointer;
	var $bitPointer;
	var $nextData = 0;
	var $nextBits = 0;
	var $andTable = array (
			511,
			1023,
			2047,
			4095 
	);
	function error($msg) {
		die ( $msg );
	}
	
	/**
	 * Method to decode LZW compressed data.
	 *
	 * @param
	 *        	string data The compressed data.
	 */
	function decode($data) {
		if ($data [0] == 0x00 && $data [1] == 0x01) {
			$this->error ( 'LZW flavour not supported.' );
		}
		
		$this->initsTable ();
		
		$this->data = $data;
		$this->dataLength = strlen ( $data );
		
		// Initialize pointers
		$this->bytePointer = 0;
		$this->bitPointer = 0;
		
		$this->nextData = 0;
		$this->nextBits = 0;
		
		$oldCode = 0;
		
		$string = '';
		$uncompData = '';
		
		while ( ($code = $this->getNextCode ()) != 257 ) {
			if ($code == 256) {
				$this->initsTable ();
				$code = $this->getNextCode ();
				
				if ($code == 257) {
					break;
				}
				
				$uncompData .= $this->sTable [$code];
				$oldCode = $code;
			} else {
				
				if ($code < $this->tIdx) {
					$string = $this->sTable [$code];
					$uncompData .= $string;
					
					$this->addStringToTable ( $this->sTable [$oldCode], $string [0] );
					$oldCode = $code;
				} else {
					$string = $this->sTable [$oldCode];
					$string = $string . $string [0];
					$uncompData .= $string;
					
					$this->addStringToTable ( $string );
					$oldCode = $code;
				}
			}
		}
		
		return $uncompData;
	}
	
	/**
	 * Initialize the string table.
	 */
	function initsTable() {
		$this->sTable = array ();
		
		for($i = 0; $i < 256; $i ++)
			$this->sTable [$i] = chr ( $i );
		
		$this->tIdx = 258;
		$this->bitsToGet = 9;
	}
	
	/**
	 * Add a new string to the string table.
	 */
	function addStringToTable($oldString, $newString = '') {
		$string = $oldString . $newString;
		
		// Add this new String to the table
		$this->sTable [$this->tIdx ++] = $string;
		
		if ($this->tIdx == 511) {
			$this->bitsToGet = 10;
		} else if ($this->tIdx == 1023) {
			$this->bitsToGet = 11;
		} else if ($this->tIdx == 2047) {
			$this->bitsToGet = 12;
		}
	}
	
	// Returns the next 9, 10, 11 or 12 bits
	function getNextCode() {
		if ($this->bytePointer == $this->dataLength) {
			return 257;
		}
		
		$this->nextData = ($this->nextData << 8) | (ord ( $this->data [$this->bytePointer ++] ) & 0xff);
		$this->nextBits += 8;
		
		if ($this->nextBits < $this->bitsToGet) {
			$this->nextData = ($this->nextData << 8) | (ord ( $this->data [$this->bytePointer ++] ) & 0xff);
			$this->nextBits += 8;
		}
		
		$code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable [$this->bitsToGet - 9];
		$this->nextBits -= $this->bitsToGet;
		
		return $code;
	}
	function encode($in) {
		$this->error ( "LZW encoding not implemented." );
	}
}